package SSF.OS.NetFlow;

import SSF.OS.*;
import SSF.Net.*;
import java.io.*;

//update: ipToString moved, using SSF.Net.Util.IP_s.IPtoString instead

/**
 * This is an ABSTRACT class that only includs few implemented functions 
 * that would be helpful to most kinds of netflows.
 */
public abstract class NetFlow
{

    /** next pointer */
    public NetFlow next = null;

    ////////////////////// public methods  ///////////////////////////////

    /**
     * Generate a byte array from this record.
     * @ret an byte array consists of the data of this record
     */
    public abstract byte[] dumpToBytes();

    /**
     * extract the record information from a byte array
     * @param bytes the byte array that stores the data
     * @param len the length of the data stored in the array (Not the length of the array)
     */
    public abstract void readFromBytes(byte[] bytes, int len);

    /**
     * Dump the flow to a stream
     * @param outStream the outputStream into which the data is dumped.
     */
    public void dumpBinaryOut(DataOutputStream outStream)
    {
    //NOTICE: this is used before the function dumpToBytes is written.
    // It's obsolete after that.
    //
    //It's left here not as an abstract function because most likely the user
    // won't need this function in their extended class. In the next release,
    // it may just disappear.
    }

    /**
     * read data from a binary stream
     */
    public void readBinaryIn(DataInputStream inStream)
    {
    // NOTICE: this is used before the function readFromBytes is written.
    // It's obsolete after that.
    // It's left here not as an abstract function because most likely the user
    // won't need this function in their extended class. In the next release,
    // it may just disappear.
    }

    /**
     * construct a key for this flow that can be used as hash key.
     */
    public  abstract Long makeKey();
 
    /**
     * remove the give flow from the list with this flow as the head
     * return the rest of the list
     */
    public NetFlow removeFlow(NetFlow flow)
    {
	NetFlow tFlow;

	if (this == flow) {
	    //-- the head is the one to be removed
	    tFlow = this.next;
	    this.next = null;
	    return tFlow;
	}
	else {
	    //-- not the head
	    for (tFlow = this; tFlow != null; tFlow = tFlow.next) {
		if (tFlow.next == flow) {
		    tFlow.next = flow.next;
		    flow.next = null;
		    return this;
		}
	    }
	    //-- not found
	    System.err.println("Error: attempt to remove non-existing flow in NetFlow.removeFlow");
	    return this;
	}	    
    }

    /**
     * recordSize
     * the "next" field is NOT included when count the size of the record.
     * @ret  return the size in bytes of an instance ("next" field excluded).
     */
    public int recordSize() { return 0; }

    /**
     *  check whether the given packet belongs to this flow
     *	since we may have different standards (resolution) of
     *  flows, this is an abstract method here
     * @param packet the packet to be checked.
     */
    public abstract boolean acceptPacket(ProtocolMessage packet);

    /** update the flow for the given packet
     * @param packet given packet
     * @param inID index of the incoming NIC
     * @param outID index of the outgoing NIC
     * @param curTime the current time
     */
    public abstract void update(ProtocolMessage packet,
				float curTime);
}











